<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
    <!-- Use Chrome Frame in IE -->
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
    />
    <meta name="description" content="Interaction examples with 3D Tiles." />
    <meta name="cesium-sandcastle-labels" content="3D Tiles" />
    <title>Cesium Demo</title>
    <script type="text/javascript" src="../Sandcastle-header.js"></script>
    <script
      type="text/javascript"
      src="../../../Build/CesiumUnminified/Cesium.js"
      nomodule
    ></script>
    <script type="module" src="../load-cesium-es6.js"></script>
  </head>
  <body
    class="sandcastle-loading"
    data-sandcastle-bucket="bucket-requirejs.html"
  >
    <style>
      @import url(../templates/bucket.css);
      #toolbar {
        background: rgba(42, 42, 42, 0.8);
        padding: 4px;
        border-radius: 4px;
      }
      #toolbar .header {
        font-weight: bold;
        padding-top: 5px;
        padding-bottom: 5px;
      }
    </style>
    <div id="cesiumContainer" class="fullSize"></div>
    <div id="loadingOverlay"><h1>Loading...</h1></div>
    <div id="toolbar">
      <div class="header">Right click action:</div>
      <div>
        <input
          type="radio"
          value="annotate"
          data-bind="checked: rightClickAction"
        />Annotate
      </div>
      <div>
        <input
          type="radio"
          value="properties"
          data-bind="checked: rightClickAction"
        />Print metadata
      </div>
      <div>
        <input
          type="radio"
          value="zoom"
          data-bind="checked: rightClickAction"
        />Zoom to feature
      </div>
      <div class="header">Middle click action:</div>
      <div>
        <input
          type="radio"
          value="hide"
          data-bind="checked: middleClickAction"
        />Hide feature
      </div>
    </div>
    <script id="cesium_sandcastle_script">
      function startup(Cesium) {
        "use strict";
        //Sandcastle_Begin
        const viewer = new Cesium.Viewer("cesiumContainer", {
          terrainProvider: Cesium.createWorldTerrain(),
        });

        const scene = viewer.scene;
        if (!scene.pickPositionSupported) {
          window.alert("This browser does not support pickPosition.");
        }

        scene.globe.depthTestAgainstTerrain = true;

        const viewModel = {
          rightClickAction: "annotate",
          middleClickAction: "hide",
        };

        Cesium.knockout.track(viewModel);

        const toolbar = document.getElementById("toolbar");
        Cesium.knockout.applyBindings(viewModel, toolbar);

        const annotations = scene.primitives.add(new Cesium.LabelCollection());

        // Set the initial camera view to look at Manhattan
        const initialPosition = Cesium.Cartesian3.fromDegrees(
          -74.01881302800248,
          40.69114333714821,
          753
        );
        const initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(
          21.27879878293835,
          -21.34390550872461,
          0.0716951918898415
        );
        scene.camera.setView({
          destination: initialPosition,
          orientation: initialOrientation,
          endTransform: Cesium.Matrix4.IDENTITY,
        });

        // Load the NYC buildings tileset.
        const tileset = new Cesium.Cesium3DTileset({
          url: Cesium.IonResource.fromAssetId(75343),
        });
        scene.primitives.add(tileset);
        tileset.style = new Cesium.Cesium3DTileStyle({
          meta: {
            description: "'Building ${BIN} has height ${Height}.'",
          },
        });

        const handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);

        handler.setInputAction(function (movement) {
          const feature = scene.pick(movement.position);
          if (!Cesium.defined(feature)) {
            return;
          }

          const action = viewModel.rightClickAction;
          if (action === "annotate") {
            annotate(movement, feature);
          } else if (action === "properties") {
            printProperties(movement, feature);
          } else if (action === "zoom") {
            zoom(movement, feature);
          }
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

        handler.setInputAction(function (movement) {
          const feature = scene.pick(movement.position);
          if (!Cesium.defined(feature)) {
            return;
          }

          const action = viewModel.middleClickAction;
          if (action === "hide") {
            feature.show = false;
          }
        }, Cesium.ScreenSpaceEventType.MIDDLE_CLICK);

        function annotate(movement, feature) {
          if (scene.pickPositionSupported) {
            const cartesian = scene.pickPosition(movement.position);
            if (Cesium.defined(cartesian)) {
              const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
              const height = `${cartographic.height.toFixed(2)} m`;

              annotations.add({
                position: cartesian,
                text: height,
                showBackground: true,
                font: "14px monospace",
                horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
              });
            }
          }
        }

        function printProperties(movement, feature) {
          console.log("Properties:");
          const propertyNames = feature.getPropertyNames();
          const length = propertyNames.length;
          for (let i = 0; i < length; ++i) {
            const propertyName = propertyNames[i];
            console.log(
              `  ${propertyName}: ${feature.getProperty(propertyName)}`
            );
          }

          // Evaluate feature description
          console.log(
            `Description : ${tileset.style.meta.description.evaluate(feature)}`
          );
        }

        function zoom(movement, feature) {
          const longitude = Cesium.Math.toRadians(
            feature.getProperty("Longitude")
          );
          const latitude = Cesium.Math.toRadians(
            feature.getProperty("Latitude")
          );
          const height = feature.getProperty("Height");

          const positionCartographic = new Cesium.Cartographic(
            longitude,
            latitude,
            height * 0.5
          );
          const position = scene.globe.ellipsoid.cartographicToCartesian(
            positionCartographic
          );

          const camera = scene.camera;
          const heading = camera.heading;
          const pitch = camera.pitch;

          const offset = offsetFromHeadingPitchRange(
            heading,
            pitch,
            height * 2.0
          );

          const transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
          Cesium.Matrix4.multiplyByPoint(transform, offset, position);

          camera.flyTo({
            destination: position,
            orientation: {
              heading: heading,
              pitch: pitch,
            },
            easingFunction: Cesium.EasingFunction.QUADRATIC_OUT,
          });
        }

        function offsetFromHeadingPitchRange(heading, pitch, range) {
          pitch = Cesium.Math.clamp(
            pitch,
            -Cesium.Math.PI_OVER_TWO,
            Cesium.Math.PI_OVER_TWO
          );
          heading = Cesium.Math.zeroToTwoPi(heading) - Cesium.Math.PI_OVER_TWO;

          const pitchQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_Y,
            -pitch
          );
          const headingQuat = Cesium.Quaternion.fromAxisAngle(
            Cesium.Cartesian3.UNIT_Z,
            -heading
          );
          const rotQuat = Cesium.Quaternion.multiply(
            headingQuat,
            pitchQuat,
            headingQuat
          );
          const rotMatrix = Cesium.Matrix3.fromQuaternion(rotQuat);

          const offset = Cesium.Cartesian3.clone(Cesium.Cartesian3.UNIT_X);
          Cesium.Matrix3.multiplyByVector(rotMatrix, offset, offset);
          Cesium.Cartesian3.negate(offset, offset);
          Cesium.Cartesian3.multiplyByScalar(offset, range, offset);
          return offset;
        }

        //Sandcastle_End
        Sandcastle.finishedLoading();
      }
      if (typeof Cesium !== "undefined") {
        window.startupCalled = true;
        startup(Cesium);
      }
    </script>
  </body>
</html>
